It is a common practice in PVM programs to start a task by hand, and then determine the machine configuration inside this task via the pvm_config() call, so as to dynamically spawn tasks on the machines in the current configuration. You must replace this practice with a static determination of the hosts and tasks that form an MPI parallel program.
The rest of this section discusses the three programming models supported by PVM and how to perform initial environment setup for each case.
For this scenario, the initial parallel environment setup consists of specifying the hosts to run the n tasks on. You can accomplish this setup using the mechanism provided on top of the MPI library. For example, the setup can use a hostfile for mpirun or the procgroup file for the MPICH implementation.
Here, the change involves figuring out how many PVM tasks are spawned in total (including those started by hand and those dynamically spawned), and on what machines these tasks are run. These two pieces of information can be directly translated into information (number of MPI tasks and the hosts on which these are to be run) that the hostfile/procgroup file of the MPI setup requires.
You must remove all instances of the pvm_spawn() call from the program. Most of the options of this call can be dealt by a translation into the MPI initial setup. The option PvmTaskDebug has no counterpart in MPI, so the corresponding MPI task cannot be started in debug mode. The option PvmTaskTrace and its subsequent use with a tool such as XPVM can be translated to whatever profiling interface and tools are available in the given MPI implementation.
Similarly, you should also eliminate all calls to pvm_addhosts(), pvm_delhosts(), and pvm_config(). Finally, if the program has a pvm_halt() call, remove it also.
The initial MPI environment setup thus consists of figuring out the number of instances of each distinct executable that constitute the parallel job, and using the total as the static initial number for the MPI environment. Again, you must remove all the pvm_spawn(), pvm_config(), pvm_addhosts(), pvm_delhosts(), and pvm_halt() calls in each PVM executable.
Since tasks cannot enroll in and leave from an MPI run time environment more than once, you must change all PVM tasks to reflect this requirement. Typically, a PVM task enrolls via the pvm_mytid() call; in the absence of this call, the first PVM call enrolls the calling task. Additionally, a task can call pvm_mytid() several times in a program with or without interleaved pvm_exit() calls. If it is not interleaved with pvm_exit() calls, the calling task simply gets its task ID back from the PVM library on the second and subsequent pvm_mytid() calls. You can easily eliminate these subsequent pvm_mytid() calls from the program by saving the value of the task ID and passing it around.
Replace the first pvm_mytid() call in a PVM program with the MPI_Init() routine, which must precede all other MPI routines and must be called exactly once. Since an MPI implementation can add its own command-line arguments to be processed by MPI_Init(), you must place all the user's command-line processing (anything that accesses argc and argv) after MPI_Init(). This requirement is in contrast to PVM programs, since PVM does not add its own arguments to those of the tasks being started.
To find out the number of tasks in the parallel job and its own task ID, an MPI task must call the functions MPI_Comm_size() and MPI_Comm_rank(). Thus the initial portion of a typical MPI program looks like the following:
/* Initialize the MPI environment. */ MPI_Init(&argc, &argv); /* Get task id and the total number of tasks. */ /* The rank is essentially the task id. */ MPI_Comm_rank(MPI_COMM_WORLD, &taskId); MPI_Comm_size(MPI_COMM_WORLD, &numTasks);